package com.smile.frame.alibaba.services.gateway.predicate;

import cn.hutool.core.util.StrUtil;
import lombok.*;
import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.cloud.gateway.handler.predicate.GatewayPredicate;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;

import javax.annotation.PostConstruct;
import java.util.*;
import java.util.function.Predicate;

/**
 * 请求头指定用户断言
 *
 * @author LGC
 */
@Component
public class HeaderUsernameRoutePredicateFactory extends AbstractRoutePredicateFactory<HeaderUsernameRoutePredicateFactory.Config> {
    private static final String USERNAME = "Username";
    private Set<String> usernameSet;

    /**
     * 内置用户
     */
    @PostConstruct
    public void initUsername() {
        usernameSet = new HashSet<>();
        for (int i = 1; i <= 100; i++) {
            usernameSet.add("liugch" + i);
        }
    }

    public HeaderUsernameRoutePredicateFactory() {
        super(Config.class);
    }

    @Override
    public ShortcutType shortcutType() {
        return ShortcutType.GATHER_LIST;
    }

    @Override
    public List<String> shortcutFieldOrder() {
        return Collections.singletonList("Username");
    }

    @Override
    public Predicate<ServerWebExchange> apply(Config config) {
        // yml配置的账户
        Set<String> usernames = config.getUsername();
        // 内置账户
        usernames.addAll(usernameSet);

        return new GatewayPredicate() {
            @Override
            public boolean test(ServerWebExchange serverWebExchange) {
                String username = serverWebExchange.getRequest().getHeaders().getFirst(USERNAME);
                if (!StrUtil.isEmpty(username)) {
                    return usernames.contains(username);
                }
                return false;
            }

            @Override
            public String toString() {
                return String.format("Header: Username=%s", config.getUsername());
            }
        };
    }

    @Data
    public static class Config {
        private Set<String> username;
    }
}
